# -*- encoding:utf8 -*-
from staff.models import StaffInfo
from datetime import timedelta
from attendance.convert import ts2is,t2i,date2str
from workday import is_workday
from attendance.tool_func import get_or_none
from attendance.models import AttendRecord,LeaveModel

def get_shoulde_checktimes(staff,date,workshift=None, noonrest="12:30-13:30"):
    """获取该员工应该遵守的工作时间表
    

    Args:
        @workshift: 字符串，员工作息，格式"8:30-17:30"或者Flexible
        @continueday_overtime: char类型，上一个连续工作日的加班时间 ,如 '05:30'
        @leave:["8:30-12:30",]，当天的请假时间段
        @noonrest:字符串，中午休息，格式"12:31-13:29"

    Return:
        @worktimes:[(int,int),]，该员工应该遵守的工作时间段
    """
    if workshift is None:
        workshift=staff.workshift
    worktimes = [ts2is(workshift)]
    worktimes = filter_noonrest(worktimes, ts2is(noonrest))
    
    continueday_overtime=get_last_continue_workday_overtime(date, staff)
    worktimes = filter_continueday_overtime(worktimes, continueday_overtime)
    
    leave_span_list=_leave_span_list(staff, date)
    worktimes = filter_leave(worktimes, leave_span_list)
    return time_range(worktimes)


def time_range(worktimes):
    """查询时间段列表的起始时刻
    Args:
    @worktimes:应该工作的时间段列表

    Return:
    start,end:分别工作时间段中，最早与最晚的时刻。用于计算迟到与早退。
    """
    if worktimes == []:
        return 0, 0
    else:
        return worktimes[0][0], worktimes[-1][-1]
    
def filter_noonrest(worktimes, noonrest):
    """
    从worktimes中过滤掉中午休息时间，然后返回worktimes

    @noonrest:(int,int)类型，中午休息时间段
    @worktimes:[(int,int),]类型，当天该员工应该工作的时间段列表
    """
    tmp_worktimes = []
    for span in worktimes:
        tmp_worktimes.extend(subtract(span, noonrest))
    worktimes = tmp_worktimes
    return worktimes

def get_last_continue_workday_overtime(date_, staff):
    """
    Args:
    @date_:日期，格式为：'2015-10-01'
    @staff:StaffInfo的对象
    
    Return:
    空字符，或者 '10:45'
    
    """
    lastdate=date_ - timedelta(days=1)
    lastdate_str = date2str(lastdate)
    record_row = get_or_none(AttendRecord, date=lastdate_str, staff=staff)
    if record_row:
        workday, shift = is_workday(lastdate)
        if workday:
            return t2i(record_row.overtime)
    return 0

def filter_continueday_overtime(worktimes, continueday_overtime):
    """
    @continueday_overtime:int类型，前一个连续工作日的加班时间

    """

    tmp_worktimes = []
    if continueday_overtime == 0:  # 没加班,就不需要过滤时间段了
        tmp_worktimes = worktimes
    elif 0 < continueday_overtime <= 120:
        for span in worktimes:
            tmp_worktimes.extend(subtract(span, ts2is("6:00-10:00")))  # 把6:00-10：00的时间段去掉，就相当于让员工从10点开始上班了
    else:
        for span in worktimes:
            tmp_worktimes.extend(
                subtract(span, ts2is("6:00-13:00")))  # 把"6:00-12:59的时间段去掉，相当于上午不上班。--预估，下午上班时间不会早于12:59
    worktimes = tmp_worktimes
    return worktimes


def filter_leave(worktimes, leave_span_list):
    """
    从worktimes中过滤掉员工请假的时间，然后返回worktimes

    @leave:[(int,int),]，当天的请假时间段列表
    """
    if not leave_span_list:
        return worktimes
    else:
        for lv in leave_span_list:
            worktimes=_worktimes_sub_a_tuple_span(worktimes, lv)
        # out=[]
        # for wk in worktimes:
            # left=wk
            # for lv in leave_span_list:
                # if left:
                    # left=subtract(left,lv)
            # out.extend(left)
        # for l_span in leave_span_list:
            # inn = []
            # for span in worktimes:
                # tmp_worktimes.extend(subtract(span, l_span))
            #worktimes = tmp_worktimes
        return worktimes

def _worktimes_sub_a_tuple_span(worktimes,tp_span):
    """worktimes= _worktimes_sub_a_tuple_span(worktimes,(500,700))
    """
    out=[]
    for wk in worktimes:
        out.extend(subtract(wk,tp_span))
    return out

def _leave_span_list(staff,date):
    span_list=[]
    for leave in LeaveModel.objects.filter(staff=staff, start_time__startswith=date):
        if leave.submited_leave.status=='approved':  # 如果假期申请状态是通过，才会与考勤相关联
            t1 = t2i(leave.start_time.split()[1])
            t2 = t2i(leave.end_time.split()[1])
            span_list.append((t1, t2))  
    return span_list
            
def time_range(worktimes):
    """查询时间段列表的起始时刻
    Args:
    @worktimes:应该工作的时间段列表

    Return:
    start,end:分别工作时间段中，最早与最晚的时刻。用于计算迟到与早退。
    """
    if worktimes == []:
        return 0, 0
    else:
        return worktimes[0][0], worktimes[-1][-1]


def subtract(src, target):
    """时间段src减去target时间段

    Args:
        @src:(int,int)，源时间段
        @target:(int,int)，目标时间段
    Return:
        @timespan:[(int,int),]，src与target相减后的时间段

    计算规则：
    从src时间段中过滤掉target中的时间段
    例如：
    如果src: (8:30,17:30),target: (12:30,13:30) 相减后得:[(8:30,12:30),(13:30,17:30),]
    如果src: (8：30,17:30),target:(13:30,17:30),相减后得:[(8:30,13:20),]

    """
    src_start, src_end = src
    target_start, target_end = target
    span = []
    if src_start < target_start:
        if src_end < target_start:
            span.append((src_start, src_end))
        elif target_start <= src_end < target_end:
            span.append((src_start, target_start))  # 将开始点从工作段去掉
        elif target_end == src_end:
            span.append((src_start, target_start))
        elif target_end < src_end:
            span.append((src_start, target_start))
            span.append((target_end, src_end))
    elif target_start <= src_start <= target_end:
        if src_end <= target_end:  # 时间段被减完了，pass就代表就让span列表为空
            pass
        elif target_end < src_end:
            span.append((target_end, src_end))
    elif target_end < src_start:
        span.append((src_start, src_end))

    return span
